<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function Animal(name) {
            this.name = name || 'Animal';
            // 实例方法 
            this.sleep = function () {
                console.log(this.name + '正在睡觉！');
            }
        }
        // 原型方法 
        Animal.prototype.eat = function (food) {
            console.log(this.name + '正在吃：' + food);
        };
        // 原型链继承
        /*
        特点：基于原型链，既是父类的实例，也是子类的实例
        缺点：无法实现多继承
        */
        // function Cat() {}
        // Cat.prototype = new Animal();
        // Cat.prototype.name = 'cat';
        // // Test Code 
        // var cat = new Cat();
        // console.log(cat.name);
        // cat.sleep()
        // cat.eat("fish")
        // console.log(cat instanceof Animal);
        // console.log(cat instanceof Cat);
        // 结果
        // cat
        // 类的继承.html:16 cat正在睡觉！
        // 类的继承.html:21 cat正在吃：fish
        // 类的继承.html:32 true
        // 类的继承.html:33 true

        // 构造函数继承
        /*
        特点：可以实现多继承 
        缺点：只能继承父类实例的属性和方法，不能继承原型上的属性和方法。
        */
        // function Cat(name) {
        //     Animal.call(this);
        //     this.name = name || 'Tom';
        // }
        // // Test Code 
        // var cat = new Cat();
        // console.log(cat.name);
        // cat.sleep()
        // cat.eat()
        // console.log(cat instanceof Animal); // false 
        // console.log(cat instanceof Cat); // true

        // 组合继承
        /*
        特点：可以继承实例属性/方法，也可以继承原型属性/方法
        缺点：调用了两次父类构造函数，生成了两份实例
        */
        //     function Cat(name) {
        //         Animal.call(this);
        //         this.name = name || 'Tom';
        //     }
        //     Cat.prototype = new Animal();
        //     Cat.prototype.constructor = Cat; // Test Code 
        //     var cat = new Cat();
        //     console.log(cat.name);
        //    cat.sleep()
        //     cat.eat()
        //     console.log(cat instanceof Animal); // true 
        //     console.log(cat instanceof Cat); // true

        // 寄生组合继承
        /*
        通过寄生方式，砍掉父类的实例属性，这样，在调用两次父类的构造的时候，就 不会初始化两次实例方法/属性
        */
        function Cat(name) {
            Animal.call(this);
            this.name = name || 'Tom';
        }
        Cat.prototype = Animal.prototype;
        // Test Code 
        var cat = new Cat();
        console.log(cat.name);
          cat.sleep()
            cat.eat()
        console.log(cat instanceof Animal); // true 
        console.log(cat instanceof Cat); //true
    </script>
</body>

</html>